module mculib.arm.other;

import mculib.arm.utils:__Inline;

import ldc.llvmasm;

version(LDC){}else static assert(0, "Unsupported compiler");

pragma(inline,__Inline) nothrow @nogc  @trusted package:

void __CLREX()
{
	__asm("clrex","");
}

/**
    重载 __str() 函数，使其支持不同类型的指针
    Params:
        T = 指针类型
        ptr = 指针
        val = 值
    Example:
    ---
    int a = 10;
    __str(&a,10); // 将a的值设置为10
    __str!(int)(&a,20); // 将a的值设置为20
    (&a).__str(30);    // 将a的值设置为30
    ---
*/
bool __str(T:uint)(T* ptr,in val) => __STREXW(ptr,val);
bool __str(T:ushort)(T* ptr,in val) => __STREXH(ptr,val);
bool __str(T:ubyte)(T* ptr,in val) => __STREXB(ptr,val);

/**
    重载 __strRef 函数，使其支持不同类型的指针
    Params:
        T = 指针类型
        declare = 变量的引用
    Example:
    ---
    int a = 10;
    __strRef(a,20); // 将a的值设置为20
    a.__strRef(30);    // 将a的值设置为30
    ---
*/
bool __strRef(T)(auto ref T declare, in T val) => __str(T)(&declare,val);

/// 存储一个32位的立即数到地址addr
bool __STREXW(const(uint*) addr, immutable uint val) 
{
	return __asm!bool("strex $0,$2,[$1]", "=&r,r,r",addr,val);
}

/// 存储一个16位的立即数到地址addr
// ushort
bool __STREXH(const(ushort*) addr,immutable ushort val)
{
	return __asm!bool("strexh $0,$2,[$1]", "=&r,r,r",addr,val);
}
/// 存储一个8位的立即数到地址addr
// ubyte
bool __STREXB(const(ubyte*) addr, immutable ubyte val) 
{
	return __asm!bool("strexb $0,$2,[$1]", "=&r,r,r",addr,val);
}

/**
    重载 __ldr 函数，使其支持不同类型的指针
    Params:
        T = 指针类型
        ptr = 指针
    Example:
    ---
    int a = 10;
    __ldr(&a); // 读取a的值
    __ldr!(int)(&a); // 读取a的值
    (&a).__ldr();    // 读取a的值
    ---
*/
T __ldr(T:uint)(T* ptr) => __LDREXW(ptr);
T __ldr(T:ushort)(T* ptr) => __LDREXH(ptr);
T __ldr(T:ubyte)(T* ptr) => __LDREXB(ptr);

/**
    重载 __ldrRef 函数，使其支持不同类型的指针
    Params:
        T = 指针类型
        declare = 变量的引用
    Example:
    ---
    int a = 10;
    __ldrRef(a); // 读取a的值
    a.__ldrRef();    // 读取a的值
    ---
*/
T __ldrRef(T)(auto ref T declare) => __ldr(T)(&declare);

// uint
uint __LDREXW(uint* addr)
{
    return __asm!uint(
        "ldrex $0,[$1]",
        "=r,r",
        addr);
}

//ushort
ushort __LDREXH(ushort* addr)
{
    return __asm!ushort(
        "ldrexh $0,[$1]",
        "=r,r",
        addr);
}

//ubyte
ubyte __LDREXB(ubyte* addr)
{
    return __asm!ubyte(
        "ldrexb $0,[$1]",
        "=r,r",
        addr);
}
